package com.ruslan.magaz.web;

import java.util.List;

import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.data.domain.Page;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import com.ruslan.magaz.entity.Info;
import com.ruslan.magaz.entity.InfoName;
import com.ruslan.magaz.entity.User;
import com.ruslan.magaz.service.InfoService;
import com.ruslan.magaz.service.UserService;

@Controller("infoController")
@RequestMapping("/info")
public class InfoController {
	private static final Integer MAX_PER_PAGE = 15;
	private static final String ALREADY_EXISTS = "Same info already exists!";

	@Autowired
	private UserService userService;
	@Autowired
	private InfoService infoService;

	@GET
	@RequestMapping(value = "/{userId}", method = RequestMethod.GET, produces = { "application/json" })
	@ResponseBody
	public Page<Info> getInfos(@PathVariable Integer userId,
			@RequestParam(value = "page", defaultValue = "1") Integer page) {
		return infoService.getInfosByUser(userId, page - 1, MAX_PER_PAGE);
	}

	@DELETE
	@RequestMapping(value = "/delete/{infoId}", method = RequestMethod.DELETE, produces = { "application/json" })
	@ResponseBody
	public ContactsResponse deleteInfo(@PathVariable(value = "infoId") Integer infoId) {
		infoService.removeInfo(infoId);
		return new ContactsResponse("OK", null);

	}

	@GET
	@RequestMapping(value = "/names", method = RequestMethod.GET, produces = { "application/json" })
	@ResponseBody
	public List<InfoName> getInfoNames() {

		return infoService.getInfoNames();
	}

	@GET
	@RequestMapping(value = "/name/{infoNameId}", method = RequestMethod.GET, produces = { "application/json" })
	@ResponseBody
	public InfoName getInfoName(
			@PathVariable(value = "infoNameId") Integer infoNameId) {

		return infoService.getInfoNameById(infoNameId);
	}

	@PUT
	@RequestMapping(value = "/create", method = RequestMethod.PUT, produces = { "application/json" }, consumes = { "application/json" })
	@ResponseBody
	public void createInfo(@RequestBody InfoDTO infoDTO) throws IllegalFormatException, TooManyException, AlreadyExistsException {
		if (infoDTO.getUserId() == 0 || infoDTO.getInfoNameId() == 0
				|| infoDTO.getValue().trim().isEmpty()) {
			throw new IllegalFormatException("Error");
		}
		User user = userService.getUserById(infoDTO.getUserId());
		if (infoService.countInfosForUser(user) > MAX_PER_PAGE) {
			throw new TooManyException("Too many info!");
		}
		InfoName infoName = infoService.getInfoNameById(infoDTO
				.getInfoNameId());
		if (infoService.countSameInfo(infoName, infoDTO.getValue()) > 0) {
			throw new AlreadyExistsException(ALREADY_EXISTS);
		}
		Info info = new Info();
		info.setUser(user);
		info.setInfoName(infoName);
		info.setValue(infoDTO.getValue());
		infoService.addInfo(info);
	}

	@POST
	@RequestMapping(value = "/update", method = RequestMethod.POST, produces = { "application/json" }, consumes = { "application/json" })
	@ResponseBody
	public void updateInfo(@RequestBody InfoDTO infoDTO) throws IllegalFormatException, AlreadyExistsException {
//		try {
			if (infoDTO.getId() == 0 || infoDTO.getValue().trim().isEmpty()) {
				throw new IllegalFormatException("Error");
			}
			
			InfoName infoName = infoService.getInfoNameById(infoDTO
					.getInfoNameId());
			
			if (infoService.countIdenticalInfo(infoDTO.getId(), infoName, infoDTO.getValue()) > 0) {
				throw new AlreadyExistsException(ALREADY_EXISTS);
			}
			
			Info info = new Info();
			info.setId(infoDTO.getId());
			info.setUser(userService.getUserById(infoDTO.getUserId()));
			info.setInfoName(infoName);
			info.setValue(infoDTO.getValue());
			
			
			infoService.updateInfo(info);


//		} catch (Exception ex) {
//			return new ContactsResponse("ERROR", ex.getMessage());
//		}
	}
	
	    @ExceptionHandler(AlreadyExistsException.class)
	    @ResponseStatus(value=HttpStatus.CONFLICT)
	    @ResponseBody
	    public ContactsResponse handleAlreadyExistsException(AlreadyExistsException ex) {
	 
	        return new ContactsResponse("ERROR", ex.getMessage());
	   }
	    
	    @ExceptionHandler(TooManyException.class)
	    @ResponseStatus(value=HttpStatus.FAILED_DEPENDENCY)
	    @ResponseBody
	    public ContactsResponse handleTooManyException(TooManyException ex) {
	 
	        return new ContactsResponse("ERROR", ex.getMessage());
	   }
	    @ExceptionHandler(IllegalFormatException.class)
	    @ResponseStatus(value=HttpStatus.NOT_ACCEPTABLE)
	    @ResponseBody
	    public ContactsResponse handleIllegalFormatException(IllegalFormatException ex) {
	 
	        return new ContactsResponse("ERROR", ex.getMessage());
	   }
	    @ExceptionHandler(EmptyResultDataAccessException.class)
	    @ResponseStatus(value=HttpStatus.NOT_FOUND)
	    @ResponseBody
	    public ContactsResponse handleEmptyResultDataAccessException(EmptyResultDataAccessException ex) {
	 
	        return new ContactsResponse("ERROR", ex.getMessage());
	   }

}
